package com.shine.cotrun.sql.hibernate;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;

import com.shine.cotrun.security.SymmetricAlgorithm;


/**
 * com.shine.sql.hibernate.HibernateUtil
 * 
 * Hibernate工具类
 * 
 * 单子模式类
 * 提供了方便的，静态的session及Transaction获取，关闭方法。
 * 使用ThreadLocal对象维护session在一个线程操作（通常也是事务操作）中的唯一性
 * 
 * Configures and provides access to Hibernate sessions, tied to the
 * current thread of execution.  Follows the Thread Local Session
 * pattern, see {@link http://hibernate.org/42.html }.
 */
public class HibernateUtil {

    private static String CONFIG_FILE_LOCATION = "/hibernate.cfg.xml";
	private static final ThreadLocal<Session> localSession = new ThreadLocal<Session>();
	private static final ThreadLocal<Transaction> localTransaction = new ThreadLocal<Transaction>();
    private  static Configuration configuration = new Configuration();
    private static SessionFactory sessionFactory;
    private static String configFile = CONFIG_FILE_LOCATION;

	static {
    	try {
			configuration.configure(configFile);
			String encrypt = configuration.getProperty("encrypt");
			if ("true".equals(encrypt)) {
				String password = configuration.getProperty("hibernate.connection.password");
				//解密
				password = new SymmetricAlgorithm(password).desDecrypt();

				configuration.setProperty("hibernate.connection.password",password);
			
			}
			sessionFactory = configuration.buildSessionFactory();
		} catch (Exception e) {
			System.err
					.println("%%%% Error Creating SessionFactory %%%%");
			e.printStackTrace();
		}
    }
    private HibernateUtil() {
    }
	
	/**
     * Returns the ThreadLocal Session instance.  Lazy initialize
     * the <code>SessionFactory</code> if needed.
     *
     *  @return Session
     *  @throws HibernateException
     */
    public static Session getSession() throws HibernateException {
        Session session = (Session) localSession.get();

		if (session == null || !session.isOpen()) {
			if (sessionFactory == null) {
				rebuildSessionFactory();
			}
			session = (sessionFactory != null) ? sessionFactory.openSession()
					: null;
			localSession.set(session);
		}

        return session;
    }

	/**
     *  Rebuild hibernate session factory
     *
     */
	public static void rebuildSessionFactory() {
		try {
			configuration.configure(configFile);
			sessionFactory = configuration.buildSessionFactory();
		} catch (Exception e) {
			System.err.println("%%%% Error Creating SessionFactory %%%%");
			e.printStackTrace();
		}
	}

	/**
     *  Close the single hibernate session instance.
     *
     *  @throws HibernateException
     */
    public static void closeSession() throws HibernateException {
        Session session = (Session) localSession.get();
        localSession.set(null);

        if (session != null && session.isOpen()) {
            session.close();
        }
    }

	/**
     *  return session factory
     *
     */
	public static SessionFactory getSessionFactory() {
		return sessionFactory;
	}

	/**
     *  return session factory
     *
     *	session factory will be rebuilded in the next call
     */
	public static void setConfigFile(String configFile) {
		HibernateUtil.configFile = configFile;
		sessionFactory = null;
	}

	/**
     *  return hibernate configuration
     *
     */
	public static Configuration getConfiguration() {
		return configuration;
	}

	/**
	 * 开始当前线程中Hibernate Session的事务
	 * @return Transaction
	 * @throws HibernateException
	 */
	public static Transaction beginTransaction() throws HibernateException {
		Transaction tx = (Transaction)localTransaction.get();
    	if(tx == null || tx.wasCommitted() || tx.wasRolledBack()){
    		Session session = getSession(); 
    		tx = (session != null) ? session.beginTransaction() : null;
    		localTransaction.set(tx);
    	}
    	
    	return tx;
	}
	
	/**
	 * 提交当前线程中Hibernate Session的事务
	 * @throws HibernateException
	 */
	public static void commitTransaction() throws HibernateException {
		Transaction tx = (Transaction)localTransaction.get();
    	if(tx != null){
    		tx.commit();
    	}
    	localTransaction.set(null);
    }
    /**
     * 回滚当前线程中Hibernate Session的事务
     * @throws HibernateException
     */
    public static void rollbackTransaction() throws HibernateException {
    	Transaction tx = (Transaction)localTransaction.get();
    	localTransaction.set(null);
    	if(tx != null){
    		tx.rollback();
    	}
    }
    
    /**
     * 当前Hibernate Session是否打开
     * @return
     */
    public static boolean isOpenSession() {
    	Session session = (Session) localSession.get();
 		if (session != null && session.isOpen()) {
 			return true;
 		}
 		return false;
    }
	    
}